In this article we will learn about the things that are being discussed and developed by web developers. We will learn the basics of Progressive Web Apps (PWA) and later we will make a simple PWA application. Maybe some of you have been confused about creating a mobile native application or web application that can be run responsively on the mobile. Before making the PWA application, we will learn about this.
One advantage of mobile native applications is that they can run in the background, so even though the application is not active, it can still work offline. A simple example of this is that the application can still send push notifications. Of course, this cannot be done by the mobile website. To use the native mobile app you have to take a few steps first, such as visiting the store where the application is published and pay for the application, then after that, we are required to install the application we want to use. Of course, this will reduce the memory source in our device.
In the current application era, we see only a few people accessing websites via mobile. This is because the mobile web is usually slow and won’t work offline. But besides these shortcomings, the mobile web also has advantages that are the reason why there are still many who pay attention to the mobile website in their applications or business models. The mobile web is easy to access. That means when we open the browser, we only need to type the keyword or website URL then Google will appear in the search. So you no longer need to install and that certainly won’t deplete memory on your device. For that, there is a new technology on the website, namely PWA.
I will not explain much about PWAs, because you can read about them on their official website, but I will explain a bit. PWA exists to get users back to using the mobile web by offering advantages that are already present. Adding to advantages that exist in the native mobile app, PWA can access content offline, maximize your internet connection and send push notifications from the web, even if your browser is not open.
Lighthouse Extension
To develop PWA, we need additional tools in the Google Chrome extension. I will use Lighthouse. This extension is useful to provide reports about the progress of the PWA application. If it is installed, you can see the toolbar in your browser, as shown below.
Use HTTPS to serve web
One thing we don’t know about is PWAs running on HTTPS; for that we need to serve our website on HTTPS. But, if you only want to try out or learn about PWA you can use firebase as firebase has free hosting and directly uses HTTPS. You can also deploy your applications on HTTPS with the tool Zeit.
We will get acquainted with service workers and the benefits of our PWA application. The service worker is a separate script from the website itself and runs in the background. The service worker uses JavaScript and is a powerful part of PWA. A service worker allows us to handle and manage network requests, which means when the network request comes in, we can play with the cache. Service workers can control cache and send us push notifications from the mobile web even if our browser is not active. We will discuss and give examples directly in our code in the next section.
The web manifest is a JSON file that can be created with a generator. The web is data such as logos, short names, and also the start of the URL of our application. Web manifest will adjust the appearance of our application and allow us to add a home screen in the application.
I have explained briefly what service workers, web manifests and help tools are in creating PWA applications. Now we will start making our PWA. We will do two things in this section: first we will make an API for consumption by the application that we make, second we will make BaseApp for the client.
In this section, we will create an API that we will later use for the client. To save time, I will make the API using https://my-json-server.typicode.com/, but if you want to create your own API please do. To use the API that we created on my JSON server we need to make a repository on GitHub for JSON push that we use as an API. After we push db.json to our repository, we can use an endpoint like this; I will make db.json as data that we can use in the client, the name is db.json.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
"items": [
{
"id": 1,
"name": "Rabbits",
"type": "Animal"
},
{
"id": 2,
"name": "Cat",
"type": "Animal"
},
{
"id": 3,
"name": "Cucumber",
"type": "fruit"
},
{
"id": 4,
"name": "apple",
"type": "fruit"
}
]
}
https://my-json-server.typicode.com/<your-username>/<your-repo>/yourFile.json
https://my-json-server.typicode.com/iqbalhood/THRIVE-PWA/db
In this section, we will create static parts of the application, such as making HTML and CSS as the initial foundation of our application. I will use JQuery; for that I will load via CDN and I will create a folder for JavaScript in folder JS. For more details, you can see the code below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
index.html < !DOCTYPE html > <html> <head> <title>PWA Aplication</title> </head> <body> <h1>Learn PWA from basics</h1> <div id="results"></div> <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> <script type="text/javascript"src='js/main.js'></script> </body> </html>
After we create a static file in HTML, we will create a JavaScript file that will be the main script to manage our PWA application. First we will access data from the API via JQuery Ajax. The following is an example.
1
2
3
4
5
6
7
8
9
main.js
$(document)
.ready(function () {
//set url
var _url = 'https://my-json-server.typicode.com/iqbalhood/THRIVE-PWA/db';
$.get(_url, function (data) {
console.log(data);
})
});
$(document).ready(function(){}
: Because we use jquery we can use document.ready () to make sure the element has been loaded.
Set endpoint API: at the top, we have made an endpoint for us to use, the endpoint is https://my-json-server.typicode.com/iqbalhood/THRIVE-PWA/db which contains data in the form of JSON.
Use Jquery ajax: we use jquery ajax to make a request to the endpoint, using the $ .get ()
method. After that, we will do console.log(data)
to see the response of the data. If it works, then we can see it as shown below.
We have fetched data from the API. Now we will display the data in the frontend section in HTML, therefore, we will use jquery $ .each() to loop in the HTML element; here is an example.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
main.js
$(document)
.ready(function () {
//set url
var results = '';
var _url = 'https://my-json-server.typicode.com/iqbalhood/THRIVE-PWA';
$.get(_url, function (data) {
$.each(data.items, function (key, items) {
console.log(items);
results += "<div>" +
"<h4>" + items.type + "</h3>" +
"<li>" + items.name + "</li>"
"</div>";
})
$('#results')
.html(results);
})
});
Looping data: to loop we can use the $.each ()
function. In that function we have two mandatory parameters; namely the first parameter is the data that will be looped and the second is the callback function that has parameters of keys and data that has been looped $.each (data, function () {})
. We can get the data in the data.items like this $.each(data.items, function(key, items){})
.
Make an element to bind data: after we get the data we can make HTML elements to bind the data like the code below.
1 2 3 4
results += "<div>" + "<h4>" + items.type + "</h3>" + "<li>" + items.name + "</li>" "</div>";
Then we can enter the html element into <div id="results"></div>
which we have made before. We can print this element by using the html()
function in jquery $('#results').html(results);
. We will see the results as shown below:
We will get to know service workers from the start, as we know service workers are a very important part of our PWA application. The first thing we have to do is register the service worker in our application as follows.
1
2
3
4
5
6
7
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('/sw.js');
}, function (err) {
console.log("Registration failed" + err);
});
}
Check service worker: We need to know that the service worker is not running on all browsers and must use HTTPS. For that we need to check whether the service worker is available with if ('serviceWorker' in navigator)
.
Register file as service worker: After we check whether the service worker has been supported in the next web browser we will load the file that will be used as a service worker. In this tutorial I will use the sw.js file navigator.serviceWorker.register('/sw.js');
. I recommend that you place your service worker files in the root of your application folder so that service workers can handle all your applications, or in other areas, we set a service worker to work globally.
We have been acquainted with PWA and learned the basics of a PWA app, a web manifest, service workers, and how to apply the API to our PWA applications. The next tutorial will discuss more about PWAs, the service worker and web manifest workings. I hope this tutorial helps you. Thanks.
We have registered in the previous tutorial, now we will check whether the registration is running properly. We will do the console, .log() to check it. The following is the code:
1
2
3
4
5
6
7
8
9
10
11
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('sw.js')
.then(function (registration) {
console.log(registration)
console.log("registration has been successful " + registration.scope)
}, function (err) {
console.log(err)
});
});
}
I will do console.log (registration)
to see what data we can see when we successfully register. We can see more details in the picture below.
We have created the sw.js file that we use as a service worker and have also registered the file as a service worker. Now all we have to do is install and define the file service worker, such as in the code below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sw.js
var CACHE_NAME = 'my-site-cache-v1';
var urlsToCache = [
'/',
'assets/main.css',
'js/main.js',
'js/jquery.min.js'
];
self.addEventListener('install', function (event) {
event.waitUntil(
caches.open(CACHE_NAME)
.then(function (cache) {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
);
});
Install service workers: we can install the service worker in the sw.js file this way self.addEventListener('install', function(event) { }
.
Add promise: after we install the service worker we will call the waitUntil()
method. This function is a promise. We will wait until the functions are finished running.
1
2
3
4
5
caches.open(CACHE_NAME)
.then(function (cache) {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
\
Set variable: we will do some variable definitions to represent the files that we will cache.
var CACHE_NAME = 'my-site-cache-v1';
Name the cache according to what you want, but the cache name is recommended as follows 'my-site-cache-v1. If later there are changes or additions you can add versions like ‘my-site-cache-v1’, ‘my-site-cache-v2’, ‘my-site-cache-v3’. For more details we will do console.log () to see if change is open.
In the picture above we see that we have managed to cache my-site-cache-v1 and we can also see the file or directory file that we registered has been cached. When we reload our web page, we no longer need to pull the data we need to use the cache.
var urlsToCache =[]
, The second parameter is the URL or directory of the files that we will cache. We can define it in array form. In this tutorial, I have the CSS ‘/assets/main.css’ , jQuery ‘/js/jquery.min.js’ and the own javascript /js/main.js, that we will cache - and don’t forget to return those variable like this return cache.addAll(urlsToCache)
. There are a few changes; if previously written we use CDN, then I suggest you download the jquery script and run it locally, so that it is easier to cache the jquery.
Change
\
1 2 3 4 5 6 7 8 9 10 11 12
<!DOCTYPE html> <html> <head> <title>PWA Aplication</title> </head> <body> <h1>Learn PWA from basics</h1> <div id="results"></div> <script src="js/jquery.min.js"></script> <script type="text/javascript"src='js/main.js'></script> </body> </html>
Note: to remember the file we cache in this section is a statism file, I suggest you separate dynamic and static files.
After the installation is complete we will enter the activate. The part activated is the part that will be triggered when our web application page is closed, so we can use it when we want to replace or delete the old service worker with the latest.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
sw.js
self.addEventListener('activate', function (event) {
event.waitUntil(
caches.keys()
.then(function (cacheNames) {
return Promise.all(
cacheNames.filter(function (cacheNames) {
return cacheNames != CACHE_NAME
})
.map(function (cacheName) {
return caches.delete(cacheName)
})
);
})
);
});
Get list cache: We can get the cache key by using promise with the keys()
method.
Filter cache: We will filter cache before we map. The goal is that we will clear the cache before there is a new cache, because we will not save the old cache in memory. Therefore we will do a filter like this cacheNames.filter(function(cacheNames){ })
and we will return the value in boolean return cacheNames != CACHE_NAME. CACHE_NAME
is a variable that specifies the cache version that we have defined in the sw.js as follows var CACHE_NAME = ‘my-site-cache-v1’;.
Delete cache: we will do the mapping to delete the cache as follows return caches.delete(cacheName)
.
We have made a cache in the previous section, but haven’t actually used it. Now we will learn how to use the cache using the event fetch. This event is used to retrieve the value in the stored cache. For more details we can see the following code.
1
2
3
4
5
6
7
8
9
10
11
12
13
sw.js
self.addEventListener('fetch', function (event) {
event.respondWith(
caches.match(event.request)
.then(function (response) {
// Cache hit - return response
if (response) {
return response;
}
return fetch(event.request);
})
);
});
Fetch event: we will use fetch event to retrieve data in the cache. In this event we no longer use waitUntil()
but use respondWith()
because we will give a response.
Check cache: we will match and check whether the cache name already exists. We can see the cache at event.request. We can use promise with the match ()
method, and if the cache already exists we will receive the response to the callback function parameter that is the response caches.match(event.request).then(function(response) {}
and return the response return response;. If there is no cache we will fetch which means we will use the network. So we will again access our web URL.
When we run our web automatically we have used the cache. If you have done the tutorial correctly, then we will be able to see the results as below. I would add a picture to see the difference.
Add image in index.html
1 2 3 4 5 6 7 8 9 10 11 12 13
<!DOCTYPE html> <html> <head> <title>PWA Aplication</title> </head> <body> <h1>Learn PWA from basics</h1> <img src="assets/woman.jpg" style="width:200px;"> <div id="results"></div> <script src="js/jquery.min.js"></script> <script type="text/javascript"src='js/main.js'></script> </body> </html>
Add files to cache
I will add register for woman.jpg file to cache. We can see the results as shown:
1 2 3 4 5 6 7
var urlsToCache = [ '/', 'assets/woman.jpg', 'assets/main.css', 'js/main.js', 'js/jquery.min.js' ];
We have learned a lot from the cache in the service worker. I hope you will explore more about the cache in the service worker, this is just basic information. There is a lot that we can do with the service worker.